﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml;
using DevScope.SharePoint.Utils.BulkDelete.Helpers.Caml.Enumerations;
using DevScope.SharePoint.Utils.BulkDelete.Helpers.Caml;
using DevScope.SharePoint.Utils.BulkDelete.Helpers.Caml.Constants;

namespace DevScope.SharePoint.Utils.BulkDelete.Helpers.Caml
{
    /// <summary>
    /// Removed with reflection of: "U2U.Sharepoint.Caml"
    /// </summary>
    public class CamlBuilder
    {
        private XmlNode batchNode;
        private XmlDocument camlDocument;
        private CamlTypeEnum camlType;
        private XmlNode containsNode;
        private bool isFieldRefName;
        private XmlNode orderByNode;
        private XmlNode queryNode;
        private XmlNode queryOptionsNode;
        private XmlNode rootNode;
        private XmlNode viewFieldsNode;
        private XmlNode whereNode;

        public CamlBuilder(XmlDocument camlDocument)
        {
            this.isFieldRefName = true;
            this.camlDocument = camlDocument;
            this.GetCamlNodes();
        }

        public CamlBuilder(CamlTypeEnum camlType)
        {
            this.isFieldRefName = true;
            this.camlType = camlType;
            this.camlDocument = new XmlDocument();
            switch (camlType)
            {
                case CamlTypeEnum.Query:
                    this.queryNode = this.camlDocument.CreateElement(Query.Tag);
                    this.camlDocument.AppendChild(this.queryNode);
                    return;

                case CamlTypeEnum.GetListItems:
                    this.rootNode = this.camlDocument.CreateElement(camlType.ToString());
                    this.camlDocument.AppendChild(this.rootNode);
                    this.queryNode = this.camlDocument.CreateElement(Query.Tag);
                    this.rootNode.AppendChild(this.queryNode);
                    this.viewFieldsNode = this.camlDocument.CreateElement(ViewFields.Tag);
                    this.rootNode.AppendChild(this.viewFieldsNode);
                    this.queryOptionsNode = this.camlDocument.CreateElement(QueryOptions.Tag);
                    this.rootNode.AppendChild(this.queryOptionsNode);
                    return;

                case CamlTypeEnum.GetListItemChanges:
                    this.rootNode = this.camlDocument.CreateElement(camlType.ToString());
                    this.camlDocument.AppendChild(this.rootNode);
                    return;

                case CamlTypeEnum.GetListItemChangesSinceToken:
                    break;

                case CamlTypeEnum.UpdateListItems:
                    this.rootNode = this.camlDocument.CreateElement(camlType.ToString());
                    this.camlDocument.AppendChild(this.rootNode);
                    this.batchNode = this.camlDocument.CreateElement(Batch.Tag);
                    this.UpdateBatchNode(Batch.PreCalc, "TRUE");
                    this.rootNode.AppendChild(this.batchNode);
                    break;

                default:
                    return;
            }
        }

        public XmlNode AddContainsField(Guid fieldId, string valueString, string dataType)
        {
            if (this.queryNode != null)
            {
                throw new Exception("You can't add a Contains clause when you already build a Query for this request.");
            }
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other AddContainsField method instead.");
            }
            XmlNode newChild = this.ContainsNode.SelectSingleNode(string.Format("//{0}/{1}[.='{2}']", Contains.Tag, Contains.FieldRef.Tag, fieldId.ToString()));
            if (newChild == null)
            {
                newChild = this.camlDocument.CreateElement(Contains.FieldRef.Tag);
                XmlAttribute node = this.camlDocument.CreateAttribute(Contains.FieldRef.Attributes.ID);
                node.Value = fieldId.ToString();
                newChild.Attributes.Append(node);
                this.ContainsNode.AppendChild(newChild);
                XmlNode node2 = this.camlDocument.CreateElement(Contains.ValueType.Tag);
                node2.InnerText = valueString;
                XmlAttribute attribute2 = this.camlDocument.CreateAttribute(Contains.ValueType.Attributes.Type);
                attribute2.Value = dataType;
                node2.Attributes.Append(attribute2);
                node2.InnerText = valueString;
                this.ContainsNode.AppendChild(node2);
            }
            return newChild;
        }

        public XmlNode AddContainsField(string internalName, string valueString, string dataType)
        {
            if (this.queryNode != null)
            {
                throw new Exception("You can't add a Contains clause when you already build a Query for this request.");
            }
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other AddContainsField method instead.");
            }
            XmlNode newChild = this.ContainsNode.SelectSingleNode(string.Format("//{0}/{1}[.='{2}']", Contains.Tag, Contains.FieldRef.Tag, internalName));
            if (newChild == null)
            {
                newChild = this.camlDocument.CreateElement(Contains.FieldRef.Tag);
                XmlAttribute node = this.camlDocument.CreateAttribute(Contains.FieldRef.Attributes.Name);
                node.Value = internalName;
                newChild.Attributes.Append(node);
                this.ContainsNode.AppendChild(newChild);
                XmlNode node2 = this.camlDocument.CreateElement(Contains.ValueType.Tag);
                node2.InnerText = valueString;
                XmlAttribute attribute2 = this.camlDocument.CreateAttribute(Contains.ValueType.Attributes.Type);
                attribute2.Value = dataType;
                node2.Attributes.Append(attribute2);
                node2.InnerText = valueString;
                this.ContainsNode.AppendChild(node2);
            }
            return newChild;
        }

        public void AddFieldNode(int methodID, string fieldName, string fieldValue)
        {
            XmlNode node = this.BatchNode.SelectSingleNode(string.Format("//{0}[@{1} = {2}]", Batch.Method.Tag, Batch.Method.ID, methodID));
            if (node != null)
            {
                XmlNode newChild = node.SelectSingleNode("Field[@Name = '" + fieldName + "']");
                if (newChild != null)
                {
                    newChild.InnerText = fieldValue;
                }
                else
                {
                    newChild = this.camlDocument.CreateElement("Field");
                    XmlAttribute attribute = this.camlDocument.CreateAttribute("Name");
                    attribute.Value = fieldName;
                    newChild.Attributes.Append(attribute);
                    newChild.InnerText = fieldValue;
                    node.AppendChild(newChild);
                }
            }
        }

        public void AddMethodNode(int methodID, CamlCommandTypeEnum methodCommand)
        {
            XmlNode newChild = this.camlDocument.CreateElement("Method");
            this.BatchNode.AppendChild(newChild);
            XmlAttribute node = this.camlDocument.CreateAttribute("ID");
            node.Value = methodID.ToString();
            newChild.Attributes.Append(node);
            node = this.camlDocument.CreateAttribute("Cmd");
            node.Value = methodCommand.ToString();
            newChild.Attributes.Append(node);
        }

        public XmlNode AddOrderByField(Guid fieldId)
        {
            if (this.containsNode != null)
            {
                throw new Exception("You can't add a Order By clause when you already build a Contains clause for this request.");
            }
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the AddOrderByField method instead.");
            }
            XmlNode newChild = this.camlDocument.CreateElement("FieldRef");
            XmlAttribute node = this.camlDocument.CreateAttribute("ID");
            node.Value = fieldId.ToString();
            newChild.Attributes.Append(node);
            this.OrderByNode.AppendChild(newChild);
            return newChild;
        }

        public XmlNode AddOrderByField(string internalName)
        {
            if (this.containsNode != null)
            {
                throw new Exception("You can't add a Order By clause when you already build a Contains clause for this request.");
            }
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the AddOrderByField method instead.");
            }
            XmlNode newChild = this.camlDocument.CreateElement("FieldRef");
            XmlAttribute node = this.camlDocument.CreateAttribute("Name");
            node.Value = internalName;
            newChild.Attributes.Append(node);
            this.OrderByNode.AppendChild(newChild);
            return newChild;
        }

        public XmlNode AddOrderByField(Guid fieldId, bool isAscending)
        {
            XmlNode node = this.AddOrderByField(fieldId);
            XmlAttribute attribute = this.camlDocument.CreateAttribute("Ascending");
            attribute.Value = isAscending.ToString();
            node.Attributes.Append(attribute);
            return node;
        }

        public XmlNode AddOrderByField(Guid fieldId, string sortType)
        {
            XmlNode fieldrefNode = this.AddOrderByField(fieldId);
            if ((sortType == "Descending") || (sortType == "DESC"))
            {
                this.UpdateOrderByField(fieldrefNode, false);
            }
            return fieldrefNode;
        }

        public XmlNode AddOrderByField(string internalName, bool isAscending)
        {
            XmlNode node = this.AddOrderByField(internalName);
            XmlAttribute attribute = this.camlDocument.CreateAttribute("Ascending");
            attribute.Value = isAscending.ToString();
            node.Attributes.Append(attribute);
            return node;
        }

        public XmlNode AddOrderByField(string internalName, string sortType)
        {
            XmlNode fieldrefNode = this.AddOrderByField(internalName);
            if ((sortType == "Descending") || (sortType == "DESC"))
            {
                this.UpdateOrderByField(fieldrefNode, false);
            }
            return fieldrefNode;
        }

        public XmlNode AddQueryOptionField(string queryOption, bool value)
        {
            return this.AddQueryOptionField(queryOption, value.ToString());
        }

        public XmlNode AddQueryOptionField(string queryOption, string value)
        {
            XmlNode newChild = this.camlDocument.SelectSingleNode("//QueryOptions/" + queryOption);
            if (newChild == null)
            {
                newChild = this.camlDocument.CreateElement(queryOption);
                this.QueryOptionsNode.AppendChild(newChild);
            }
            switch (queryOption)
            {
                case "ViewAttributes":
                {
                    XmlAttribute node = this.camlDocument.CreateAttribute("Scope");
                    node.Value = "Recursive";
                    newChild.Attributes.Append(node);
                    return newChild;
                }
                case "ExtraIds":
                    if (newChild.InnerText.Length > 0)
                    {
                        newChild.InnerText = newChild.InnerText + ",";
                    }
                    newChild.InnerText = newChild.InnerText + value;
                    return newChild;
            }
            newChild.InnerText = value;
            return newChild;
        }

        public XmlNode AddViewField(string internalName)
        {
            XmlNode newChild = this.camlDocument.SelectSingleNode("//ViewFields/FieldRef[.='" + internalName + "']");
            if (newChild == null)
            {
                newChild = this.camlDocument.CreateElement("FieldRef");
                XmlAttribute node = this.camlDocument.CreateAttribute("Name");
                node.Value = internalName;
                newChild.Attributes.Append(node);
                this.ViewFieldsNode.AppendChild(newChild);
            }
            return newChild;
        }

        public XmlNode AddWhereField(Guid fieldId, string valueString, DataTypeEnum dataType, CamlOperatorEnum operatorTag, out bool addCombinerNode)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the AddWhereField method instead.");
            }
            return this.AddWhereField(fieldId.ToString(), valueString, dataType, operatorTag, CamlCombinerEnum.And, out addCombinerNode);
        }

        public XmlNode AddWhereField(string internalName, string valueString, DataTypeEnum dataType, CamlOperatorEnum operatorTag, out bool addCombinerNode)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the AddWhereField method instead.");
            }
            return this.AddWhereField(internalName, valueString, dataType, operatorTag, CamlCombinerEnum.And, out addCombinerNode);
        }

        public XmlNode AddWhereField(Guid fieldId, DateTime dateValue, DataTypeEnum dataType, CamlOperatorEnum operatorTag, CamlCombinerEnum combinerTag, out bool addCombinerNode)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the AddWhereField method instead.");
            }
            string valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(dateValue);
            return this.AddWhereField(fieldId.ToString(), valueString, dataType, operatorTag, combinerTag, out addCombinerNode);
        }

        public XmlNode AddWhereField(Guid fieldId, string valueString, DataTypeEnum dataType, CamlOperatorEnum operatorTag, CamlCombinerEnum combinerTag, out bool addCombinerNode)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the AddWhereField method instead.");
            }
            return this.AddWhereField(fieldId.ToString(), valueString, dataType, operatorTag, combinerTag, out addCombinerNode);
        }

        public XmlNode AddWhereField(string internalName, DateTime dateValue, DataTypeEnum dataType, CamlOperatorEnum operatorTag, CamlCombinerEnum combinerTag, out bool addCombinerNode)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the AddWhereField method instead.");
            }
            string valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(dateValue);
            return this.AddWhereField(internalName, valueString, dataType, operatorTag, combinerTag, out addCombinerNode);
        }

        public XmlNode AddWhereField(string internalName, string valueString, DataTypeEnum dataType, CamlOperatorEnum operatorTag, CamlCombinerEnum combinerTag, out bool addCombinerNode)
        {
            addCombinerNode = false;
            if (((operatorTag != CamlOperatorEnum.IsNull) && (operatorTag != CamlOperatorEnum.IsNotNull)) && ((valueString == null) || (valueString == string.Empty)))
            {
                throw new ApplicationException("Please, fill out a value for the selected field");
            }
            XmlNode newChild = null;
            if (this.WhereNode.HasChildNodes)
            {
                if (this.WhereNode.FirstChild.FirstChild.Name == "FieldRef")
                {
                    addCombinerNode = true;
                    newChild = this.camlDocument.CreateElement(combinerTag.ToString());
                    XmlNode firstChild = this.WhereNode.FirstChild;
                    this.WhereNode.AppendChild(newChild);
                    newChild.AppendChild(firstChild);
                }
                else
                {
                    foreach (XmlNode node3 in this.WhereNode.ChildNodes)
                    {
                        if (node3.Name == combinerTag.ToString())
                        {
                            if (node3.ChildNodes.Count == 2)
                            {
                                newChild = this.camlDocument.CreateElement(combinerTag.ToString());
                                this.WhereNode.AppendChild(newChild);
                                this.WhereNode.RemoveChild(node3);
                                newChild.AppendChild(node3);
                            }
                            else
                            {
                                newChild = node3;
                            }
                            break;
                        }
                    }
                    if (newChild == null)
                    {
                        addCombinerNode = true;
                        newChild = this.camlDocument.CreateElement(combinerTag.ToString());
                        this.WhereNode.AppendChild(newChild);
                    }
                }
            }
            XmlNode node4 = this.CreateWhereFieldNode(operatorTag.ToString(), internalName, dataType, valueString);
            if (newChild == null)
            {
                this.WhereNode.AppendChild(node4);
                return node4;
            }
            newChild.AppendChild(node4);
            return node4;
        }

        private void CheckFieldRefs()
        {
        }

        public void Clear()
        {
            if ((this.camlType == CamlTypeEnum.Query) && (this.queryNode != null))
            {
                this.camlDocument.RemoveChild(this.queryNode);
            }
            if ((this.rootNode != null) && (this.queryNode != null))
            {
                this.rootNode.RemoveChild(this.queryNode);
            }
            if ((this.rootNode != null) && (this.queryOptionsNode != null))
            {
                this.rootNode.RemoveChild(this.queryOptionsNode);
            }
            if ((this.rootNode != null) && (this.containsNode != null))
            {
                this.rootNode.RemoveChild(this.containsNode);
            }
            if ((this.rootNode != null) && (this.viewFieldsNode != null))
            {
                this.rootNode.RemoveChild(this.viewFieldsNode);
            }
            if ((this.rootNode != null) && (this.batchNode != null))
            {
                this.rootNode.RemoveChild(this.batchNode);
            }
            this.queryNode = null;
            this.orderByNode = null;
            this.whereNode = null;
            this.queryOptionsNode = null;
            this.containsNode = null;
            this.viewFieldsNode = null;
            this.batchNode = null;
            if (((this.rootNode == null) && (this.camlDocument.FirstChild != null)) && (this.camlDocument.FirstChild.ChildNodes.Count > 0))
            {
                this.camlDocument.FirstChild.RemoveAll();
            }
        }

        private XmlNode CreateWhereFieldNode(string operatorTag, string internalName, DataTypeEnum dataType, string valueString)
        {
            if (this.containsNode != null)
            {
                throw new Exception("You can't add a Where clause when you already build a Contains clause for this request.");
            }
            XmlNode node = this.camlDocument.CreateElement(operatorTag);
            XmlNode newChild = this.camlDocument.CreateElement("FieldRef");
            XmlAttribute attribute = null;
            if (this.isFieldRefName)
            {
                attribute = this.camlDocument.CreateAttribute("Name");
            }
            else
            {
                attribute = this.camlDocument.CreateAttribute("ID");
            }
            attribute.Value = internalName;
            newChild.Attributes.Append(attribute);
            node.AppendChild(newChild);
            if ((operatorTag != "IsNull") && (operatorTag != "IsNotNull"))
            {
                DateTime time;
                XmlNode node3 = this.camlDocument.CreateElement("Value");
                node3.InnerText = valueString;
                XmlAttribute attribute2 = this.camlDocument.CreateAttribute("Type");
                attribute2.Value = dataType.ToString();
                if (((dataType == DataTypeEnum.DateTime) && (valueString.Substring(0, 1) != "[")) && ((valueString.Substring(0, 6) != "<Today") && DateTime.TryParse(valueString, out time)))
                {
                    valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(time);
                }
                node3.Attributes.Append(attribute2);
                if (valueString.Substring(0, 1) != "<")
                {
                    node3.InnerText = valueString;
                }
                else
                {
                    node3.InnerXml = valueString;
                }
                node.AppendChild(node3);
            }
            return node;
        }

        private void GetCamlNodes()
        {
            string name = this.camlDocument.FirstChild.Name;
            if (name != null)
            {
                if (!(name == "Query"))
                {
                    if (!(name == "GetListItems"))
                    {
                        if (!(name == "GetListItemChanges"))
                        {
                            if (!(name == "GetListItemChangesSinceToken"))
                            {
                                if (name == "UpdateListItems")
                                {
                                    this.camlType = CamlTypeEnum.UpdateListItems;
                                    this.batchNode = this.camlDocument.SelectSingleNode("//Batch");
                                }
                                return;
                            }
                            this.camlType = CamlTypeEnum.GetListItemChangesSinceToken;
                            this.queryNode = this.camlDocument.SelectSingleNode("//Query");
                            this.containsNode = this.camlDocument.SelectSingleNode("//Contains");
                            this.viewFieldsNode = this.camlDocument.SelectSingleNode("//ViewFields");
                            this.queryOptionsNode = this.camlDocument.SelectSingleNode("//QueryOptions");
                            return;
                        }
                        this.camlType = CamlTypeEnum.GetListItemChanges;
                        this.containsNode = this.camlDocument.SelectSingleNode("//Contains");
                        this.viewFieldsNode = this.camlDocument.SelectSingleNode("//ViewFields");
                        return;
                    }
                }
                else
                {
                    this.camlType = CamlTypeEnum.Query;
                    this.queryNode = this.camlDocument.SelectSingleNode("Query");
                    this.whereNode = this.camlDocument.SelectSingleNode("Query/Where");
                    this.orderByNode = this.camlDocument.SelectSingleNode("Query/OrderBy");
                    return;
                }
                this.camlType = CamlTypeEnum.GetListItems;
                this.queryNode = this.camlDocument.SelectSingleNode("//Query");
                this.queryOptionsNode = this.camlDocument.SelectSingleNode("//QueryOptions");
                this.viewFieldsNode = this.camlDocument.SelectSingleNode("//ViewFields");
            }
        }

        public List<CamlParameter> GetEmptyParameterStructure()
        {
            List<CamlParameter> list = new List<CamlParameter>();
            switch (this.camlType)
            {
                case CamlTypeEnum.Query:
                    if (this.whereNode != null)
                    {
                        foreach (XmlNode node in this.whereNode.SelectNodes("//Value"))
                        {
                            if (node.InnerText.StartsWith("[") && node.InnerText.EndsWith("]"))
                            {
                                CamlParameter item = new CamlParameter(node.InnerText, null);
                                list.Add(item);
                            }
                        }
                        return list;
                    }
                    return null;

                case CamlTypeEnum.GetListItems:
                case CamlTypeEnum.GetListItemChanges:
                case CamlTypeEnum.GetListItemChangesSinceToken:
                    if ((this.queryNode == null) && (this.containsNode == null))
                    {
                        return null;
                    }
                    if (this.queryNode != null)
                    {
                        foreach (XmlNode node2 in this.queryNode.SelectNodes("//Value"))
                        {
                            if (node2.InnerText.StartsWith("[") && node2.InnerText.EndsWith("]"))
                            {
                                CamlParameter parameter2 = new CamlParameter(node2.InnerText, null);
                                list.Add(parameter2);
                            }
                        }
                    }
                    if (this.containsNode != null)
                    {
                        foreach (XmlNode node3 in this.containsNode.SelectNodes("//Value"))
                        {
                            if (node3.InnerText.StartsWith("[") && node3.InnerText.EndsWith("]"))
                            {
                                CamlParameter parameter3 = new CamlParameter(node3.InnerText, null);
                                list.Add(parameter3);
                            }
                        }
                    }
                    return list;

                case CamlTypeEnum.UpdateListItems:
                    if (this.batchNode == null)
                    {
                        return null;
                    }
                    foreach (XmlNode node4 in this.batchNode.SelectNodes("//Field"))
                    {
                        if (node4.InnerText.StartsWith("[") && node4.InnerText.EndsWith("]"))
                        {
                            CamlParameter parameter4 = new CamlParameter(node4.InnerText, null);
                            list.Add(parameter4);
                        }
                    }
                    return list;
            }
            return list;
        }

        public List<CamlParameter> GetEmptyParameterStructure(XmlDocument camlDocument)
        {
            this.camlDocument = camlDocument;
            this.GetCamlNodes();
            return this.GetEmptyParameterStructure();
        }

        public void RemoveBatchNode(string batchAttribute)
        {
            if ((((batchAttribute != "OnError") && (batchAttribute != "PreCalc")) && ((batchAttribute != "RootFolder") && (batchAttribute != "ListVersion"))) && (batchAttribute != "ViewName"))
            {
                throw new ApplicationException(batchAttribute + " is an invalid attribute for the Batch node of UpdateListItems");
            }
            XmlAttribute namedItem = (XmlAttribute) this.BatchNode.Attributes.GetNamedItem(batchAttribute);
            if (namedItem != null)
            {
                this.BatchNode.Attributes.Remove(namedItem);
            }
        }

        public void RemoveFieldNode(int methodID, string fieldName)
        {
            XmlNode node = this.BatchNode.SelectSingleNode("//Method[@ID = " + methodID + "]");
            if (node != null)
            {
                XmlNode oldChild = node.SelectSingleNode("Field[@Name = '" + fieldName + "']");
                if (oldChild != null)
                {
                    node.RemoveChild(oldChild);
                }
            }
        }

        public void RemoveMethodNode(int methodID)
        {
            XmlNode oldChild = this.BatchNode.SelectSingleNode("//Method[@ID = " + methodID + "]");
            if (oldChild != null)
            {
                this.BatchNode.RemoveChild(oldChild);
            }
        }

        public void RemoveOrderByField(Guid fieldId)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the RemoveOrderByField method instead.");
            }
            XmlNode oldChild = this.QueryNode.SelectSingleNode("//OrderBy/FieldRef[@ID='" + fieldId.ToString() + "']");
            if (oldChild != null)
            {
                if (oldChild.ParentNode.ChildNodes.Count == 1)
                {
                    this.QueryNode.RemoveChild(this.OrderByNode);
                    this.orderByNode = null;
                }
                else
                {
                    this.OrderByNode.RemoveChild(oldChild);
                }
            }
        }

        public void RemoveOrderByField(string internalName)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the RemoveOrderByField method instead.");
            }
            XmlNode oldChild = this.QueryNode.SelectSingleNode("//OrderBy/FieldRef[@Name='" + internalName + "']");
            if (oldChild != null)
            {
                if (oldChild.ParentNode.ChildNodes.Count == 1)
                {
                    this.QueryNode.RemoveChild(this.OrderByNode);
                    this.orderByNode = null;
                }
                else
                {
                    this.OrderByNode.RemoveChild(oldChild);
                }
            }
        }

        public void RemoveOrderByField(XmlNode fieldNode)
        {
            if (fieldNode != null)
            {
                if (fieldNode.ParentNode.ChildNodes.Count == 1)
                {
                    this.RemoveOrderByNode();
                }
                else
                {
                    this.OrderByNode.RemoveChild(fieldNode);
                }
            }
        }

        public void RemoveOrderByNode()
        {
            this.QueryNode.RemoveChild(this.orderByNode);
            this.orderByNode = null;
        }

        public void RemoveQueryOptionField(string queryOption)
        {
            XmlNode oldChild = this.camlDocument.SelectSingleNode("//QueryOptions/" + queryOption);
            if ((oldChild != null) && (oldChild.ParentNode != null))
            {
                oldChild.ParentNode.RemoveChild(oldChild);
            }
        }

        public void RemoveQueryOptionField(XmlNode queryOptionNode)
        {
            if ((queryOptionNode != null) && (queryOptionNode.ParentNode != null))
            {
                queryOptionNode.ParentNode.RemoveChild(queryOptionNode);
            }
        }

        public void RemoveViewField(Guid fieldId)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the AddViewField method instead.");
            }
            string xpath = "//ViewFields/FieldRef[@ID='" + fieldId.ToString() + "']";
            XmlNode oldChild = this.camlDocument.SelectSingleNode(xpath);
            if ((oldChild != null) && (oldChild.ParentNode != null))
            {
                oldChild.ParentNode.RemoveChild(oldChild);
            }
        }

        public void RemoveViewField(string internalName)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the AddViewField method instead.");
            }
            string xpath = "//ViewFields/FieldRef[@Name='" + internalName + "']";
            XmlNode oldChild = this.camlDocument.SelectSingleNode(xpath);
            if ((oldChild != null) && (oldChild.ParentNode != null))
            {
                oldChild.ParentNode.RemoveChild(oldChild);
            }
        }

        public void RemoveViewField(XmlNode viewFieldNode)
        {
            if ((viewFieldNode != null) && (viewFieldNode.ParentNode != null))
            {
                viewFieldNode.ParentNode.RemoveChild(viewFieldNode);
            }
        }

        public void RemoveWhereField(XmlNode fieldNode)
        {
            if (fieldNode != null)
            {
                if ((fieldNode.ParentNode.Name == "Where") && (fieldNode.ParentNode.ChildNodes.Count == 1))
                {
                    this.RemoveWhereNode();
                }
                else if ((fieldNode.ParentNode.Name == "And") || (fieldNode.ParentNode.Name == "Or"))
                {
                    XmlNode parentNode = fieldNode.ParentNode;
                    parentNode.RemoveChild(fieldNode);
                    if (parentNode.ChildNodes.Count == 1)
                    {
                        XmlNode oldChild = parentNode.ChildNodes[0];
                        parentNode.RemoveChild(oldChild);
                        parentNode.ParentNode.AppendChild(oldChild);
                        parentNode.ParentNode.RemoveChild(parentNode);
                    }
                    else if (parentNode.ChildNodes.Count == 0)
                    {
                        this.WhereNode.RemoveChild(parentNode);
                    }
                }
                else
                {
                    this.WhereNode.RemoveChild(fieldNode);
                }
            }
        }

        public void RemoveWhereField(Guid fieldId, DateTime dateValue, string operatorTag)
        {
            throw new NotImplementedException();
        }

        public void RemoveWhereField(Guid fieldId, string valueString, string operatorTag)
        {
            throw new NotImplementedException();
        }

        public void RemoveWhereField(string internalName, DateTime dateValue, string operatorTag)
        {
            throw new NotImplementedException();
        }

        public void RemoveWhereField(string internalName, string valueString, string operatorTag)
        {
            throw new NotImplementedException();
        }

        public void RemoveWhereNode()
        {
            this.QueryNode.RemoveChild(this.whereNode);
            this.whereNode = null;
        }

        public void ReplaceDateTimeParameterValues(ref List<CamlParameter> camlParameters)
        {
            foreach (CamlParameter parameter in camlParameters)
            {
                XmlNode node = this.camlDocument.SelectSingleNode("//Value [. = '" + parameter.ParameterName + "']");
                if (node != null)
                {
                    DateTime date = new DateTime(0x76c, 1, 1);
                    if (parameter.ParameterName.Substring(1, 5) == "Today")
                    {
                        date = DateTime.Today;
                    }
                    else if (parameter.ParameterName.Substring(1, 3) == "Now")
                    {
                        date = DateTime.Now;
                    }
                    else if (parameter.ParameterName.IndexOf("+") > -1)
                    {
                        date = DateTime.Parse(parameter.ParameterName.Substring(0, parameter.ParameterName.IndexOf("+")));
                    }
                    else if (parameter.ParameterName.IndexOf("-") > -1)
                    {
                        date = DateTime.Parse(parameter.ParameterName.Substring(0, parameter.ParameterName.IndexOf("-")));
                    }
                    while ((parameter.ParameterName.IndexOf("+") > -1) || (parameter.ParameterName.IndexOf("-") > -1))
                    {
                        int startIndex = 0;
                        string str = null;
                        string s = null;
                        string str3 = null;
                        if (((parameter.ParameterName.IndexOf("+") > -1) && (parameter.ParameterName.IndexOf("-") > -1)) && (parameter.ParameterName.IndexOf("+") < parameter.ParameterName.IndexOf("-")))
                        {
                            str = "+";
                        }
                        else if (((parameter.ParameterName.IndexOf("+") > -1) && (parameter.ParameterName.IndexOf("-") > -1)) && (parameter.ParameterName.IndexOf("-") < parameter.ParameterName.IndexOf("+")))
                        {
                            str = "-";
                        }
                        else if (parameter.ParameterName.IndexOf("+") > -1)
                        {
                            str = "+";
                        }
                        else
                        {
                            str = "-";
                        }
                        string str4 = null;
                        if ((parameter.ParameterName.IndexOf("+", (int) (parameter.ParameterName.IndexOf(str) + 1)) == -1) && (parameter.ParameterName.IndexOf("-", (int) (parameter.ParameterName.IndexOf(str) + 1)) == -1))
                        {
                            str4 = parameter.ParameterName.Substring(parameter.ParameterName.IndexOf(str) + 1, (parameter.ParameterName.Length - parameter.ParameterName.IndexOf(str)) - 2);
                        }
                        else if (parameter.ParameterName.IndexOf("+", (int) (parameter.ParameterName.IndexOf(str) + 1)) > -1)
                        {
                            str4 = parameter.ParameterName.Substring(parameter.ParameterName.IndexOf(str) + 1, (parameter.ParameterName.IndexOf("+", (int) (parameter.ParameterName.IndexOf(str) + 1)) - parameter.ParameterName.IndexOf(str)) - 1);
                        }
                        else
                        {
                            str4 = parameter.ParameterName.Substring(parameter.ParameterName.IndexOf(str) + 1, (parameter.ParameterName.IndexOf("-", (int) (parameter.ParameterName.IndexOf(str) + 1)) - parameter.ParameterName.IndexOf(str)) - 1);
                        }
                        startIndex = 0;
                        while (startIndex < str4.Length)
                        {
                            if (!DevScope.SharePoint.Utils.BulkDelete.Helpers.Caml.CamlHelper.IsNumeric(str4.Substring(startIndex, 1)))
                            {
                                break;
                            }
                            s = s + str4.Substring(startIndex, 1);
                            startIndex++;
                        }
                        str3 = str4.Substring(startIndex, str4.Length - startIndex);
                        double num2 = 0.0;
                        int months = 0;
                        if (str == "+")
                        {
                            num2 = double.Parse(s);
                            months = int.Parse(s);
                        }
                        else
                        {
                            num2 = double.Parse(s) * -1.0;
                            months = int.Parse(s) * -1;
                        }
                        switch (str3)
                        {
                            case "Day(s)":
                                date = date.AddDays(num2);
                                break;

                            case "Month(s)":
                                date = date.AddMonths(months);
                                break;

                            case "Year(s)":
                                date = date.AddYears(months);
                                break;

                            case "Hours(s)":
                                date = date.AddHours((double) months);
                                break;

                            case "Minute(s)":
                                date = date.AddMinutes(num2);
                                break;

                            case "Second(s)":
                                date = date.AddSeconds(num2);
                                break;

                            default:
                                throw new Exception("The DateTime parameter is invalid");
                        }
                        parameter.ParameterName = parameter.ParameterName.Substring(parameter.ParameterName.IndexOf(str) + 1);
                    }
                    node.InnerText = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(date);
                }
            }
        }

        public void UpdateBatchNode(string batchAttribute, string value)
        {
            if ((((batchAttribute != "OnError") && (batchAttribute != "PreCalc")) && ((batchAttribute != "RootFolder") && (batchAttribute != "ListVersion"))) && (batchAttribute != "ViewName"))
            {
                throw new ApplicationException(batchAttribute + " is an invalid attribute for the Batch node of UpdateListItems");
            }
            XmlAttribute namedItem = (XmlAttribute) this.BatchNode.Attributes.GetNamedItem(batchAttribute);
            if (namedItem == null)
            {
                namedItem = this.camlDocument.CreateAttribute(batchAttribute);
                this.BatchNode.Attributes.Append(namedItem);
            }
            namedItem.Value = value;
        }

        public void UpdateFieldNode(int methodID, string fieldName, string fieldValue)
        {
            XmlNode node = this.BatchNode.SelectSingleNode("//Method[@ID = " + methodID + "]");
            if (node != null)
            {
                XmlNode node2 = node.SelectSingleNode("Field[@Name = '" + fieldName + "']");
                if (node2 != null)
                {
                    node2.InnerText = fieldValue;
                }
            }
        }

        public void UpdateMethodNode(int methodID, CamlCommandTypeEnum methodCommand)
        {
            if (((methodCommand != CamlCommandTypeEnum.New) && (methodCommand != CamlCommandTypeEnum.Update)) && (methodCommand != CamlCommandTypeEnum.Delete))
            {
                throw new ApplicationException(methodCommand + " is an invalid attribute for the Method node of UpdateListItems");
            }
            XmlNode node = this.BatchNode.SelectSingleNode("//Method[@ID = " + methodID + "]");
            if (node != null)
            {
                XmlAttribute namedItem = (XmlAttribute) node.Attributes.GetNamedItem("Cmd");
                if (namedItem != null)
                {
                    namedItem.Value = methodCommand.ToString();
                }
            }
        }

        public XmlNode UpdateOrderByField(Guid fieldId, bool isAscending)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the UpdateOrderByField method instead.");
            }
            XmlNode fieldrefNode = this.QueryNode.SelectSingleNode("//OrderBy/FieldRef[@ID='" + fieldId.ToString() + "']");
            if (fieldrefNode != null)
            {
                return this.UpdateOrderByField(fieldrefNode, isAscending);
            }
            return null;
        }

        public XmlNode UpdateOrderByField(Guid fieldId, string sortType)
        {
            bool isAscending = false;
            if (sortType == "Ascending")
            {
                isAscending = true;
            }
            return this.UpdateOrderByField(fieldId, isAscending);
        }

        public XmlNode UpdateOrderByField(string internalName, bool isAscending)
        {
            if (!this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field id. Use the other overload of the UpdateOrderByField method instead.");
            }
            XmlNode fieldrefNode = this.QueryNode.SelectSingleNode("//OrderBy/FieldRef[@Name='" + internalName + "']");
            if (fieldrefNode != null)
            {
                return this.UpdateOrderByField(fieldrefNode, isAscending);
            }
            return null;
        }

        public XmlNode UpdateOrderByField(string internalName, string sortType)
        {
            bool isAscending = false;
            if (sortType == "Ascending")
            {
                isAscending = true;
            }
            return this.UpdateOrderByField(internalName, isAscending);
        }

        public XmlNode UpdateOrderByField(XmlNode fieldrefNode, bool isAscending)
        {
            if (fieldrefNode == null)
            {
                return null;
            }
            XmlAttribute namedItem = (XmlAttribute) fieldrefNode.Attributes.GetNamedItem("Ascending");
            if ((namedItem == null) && !isAscending)
            {
                namedItem = this.camlDocument.CreateAttribute("Ascending");
                namedItem.Value = isAscending.ToString();
                fieldrefNode.Attributes.Append(namedItem);
                return fieldrefNode;
            }
            if (namedItem != null)
            {
                namedItem.Value = isAscending.ToString();
            }
            return fieldrefNode;
        }

        public XmlNode UpdateOrderByField(XmlNode fieldrefNode, string sortType)
        {
            bool isAscending = false;
            if (sortType == "Ascending")
            {
                isAscending = true;
            }
            return this.UpdateOrderByField(fieldrefNode, isAscending);
        }

        public XmlNode UpdateWhereField(XmlNode fieldNode, DateTime dateValue)
        {
            string valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(dateValue);
            return this.UpdateWhereField(fieldNode, valueString);
        }

        public XmlNode UpdateWhereField(XmlNode fieldNode, string valueString)
        {
            if (fieldNode.FirstChild.Name != "FieldRef")
            {
                throw new ApplicationException("You passed an invalid node. The node should be of the format <Eq><FieldRef>.....</Eq>.");
            }
            XmlNode node = fieldNode.SelectSingleNode("Value");
            if (node != null)
            {
                node.InnerText = valueString;
            }
            return fieldNode;
        }

        public XmlNode UpdateWhereField(XmlNode fieldNode, DateTime dateValue, CamlOperatorEnum operatorTag)
        {
            string valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(dateValue);
            return this.UpdateWhereField(fieldNode, valueString, DataTypeEnum.Text, operatorTag);
        }

        public XmlNode UpdateWhereField(Guid fieldId, CamlOperatorEnum operatorTag, DateTime oldDateValue, DateTime newDateValue)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the UpdateWhereField method instead.");
            }
            return this.UpdateWhereField(fieldId.ToString(), operatorTag, oldDateValue, newDateValue);
        }

        public XmlNode UpdateWhereField(Guid fieldId, CamlOperatorEnum operatorTag, string oldValueString, string newValueString)
        {
            if (this.isFieldRefName)
            {
                throw new Exception("You cannot use this method when you want to query by field name. Use the other overload of the UpdateWhereField method instead.");
            }
            return this.UpdateWhereField(fieldId.ToString(), operatorTag, oldValueString, newValueString);
        }

        public XmlNode UpdateWhereField(string internalName, CamlOperatorEnum operatorTag, DateTime oldDateValue, DateTime newDateValue)
        {
            string oldValueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(oldDateValue);
            string newValueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(newDateValue);
            return this.UpdateWhereField(internalName, operatorTag, oldValueString, newValueString);
        }

        public XmlNode UpdateWhereField(string internalName, CamlOperatorEnum operatorTag, string oldValueString, string newValueString)
        {
            string xpath = null;
            if (this.isFieldRefName)
            {
                xpath = "//Where/*/FieldRef[@Name='" + internalName + "']";
            }
            else
            {
                xpath = "//Where/*/FieldRef[@ID='" + internalName + "']";
            }
            XmlNodeList list = this.QueryNode.SelectNodes(xpath);
            if ((list == null) || (list.Count == 0))
            {
                if (this.isFieldRefName)
                {
                    xpath = "//Where/*/" + operatorTag + "/FieldRef[@Name='" + internalName + "']";
                }
                else
                {
                    xpath = "//Where/*/" + operatorTag + "/FieldRef[@ID='" + internalName + "']";
                }
                list = this.QueryNode.SelectNodes(xpath);
            }
            if (list.Count == 1)
            {
                bool flag;
                XmlNode parentNode = list[0].ParentNode.ParentNode;
                DataTypeEnum dataType = DataTypeEnum.Text;
                XmlAttribute namedItem = (XmlAttribute) list[0].FirstChild.NextSibling.Attributes.GetNamedItem("Type");
                if (namedItem != null)
                {
                    dataType = (DataTypeEnum)Enum.Parse(typeof(DataTypeEnum), namedItem.Value);
                }
                CamlCombinerEnum combinerTag = CamlCombinerEnum.And;
                if (parentNode.Name != "Where")
                {
                    combinerTag = (CamlCombinerEnum)Enum.Parse(typeof(CamlCombinerEnum), parentNode.Name);
                }
                parentNode.RemoveChild(list[0].ParentNode);
                return this.AddWhereField(internalName, newValueString, dataType, operatorTag, combinerTag, out flag);
            }
            if (list.Count > 1)
            {
                throw new ApplicationException("Cannot execute the update because more than 1 node with the same FieldRef exists in the WHERE clause.");
            }
            return null;
        }

        public XmlNode UpdateWhereField(XmlNode fieldNode, string valueString, DataTypeEnum dataType, CamlOperatorEnum operatorTag)
        {
            if (fieldNode.FirstChild.Name != "FieldRef")
            {
                throw new ApplicationException("You passed an invalid node. The node should be of the format <Eq><FieldRef>.....</Eq>.");
            }
            if (((operatorTag != CamlOperatorEnum.IsNull) && (operatorTag != CamlOperatorEnum.IsNotNull)) && (valueString == string.Empty))
            {
                throw new ApplicationException("Please, fill out a value for the selected field");
            }
            string internalName = null;
            XmlAttribute namedItem = null;
            if (this.isFieldRefName)
            {
                namedItem = (XmlAttribute) fieldNode.FirstChild.Attributes.GetNamedItem("Name");
            }
            else
            {
                namedItem = (XmlAttribute) fieldNode.FirstChild.Attributes.GetNamedItem("ID");
            }
            if (namedItem == null)
            {
                throw new ApplicationException("You passed an invalid FieldRef node within the incoming node");
            }
            internalName = namedItem.Value;
            if (fieldNode.Name != operatorTag.ToString())
            {
                bool flag;
                this.RemoveWhereField(fieldNode);
                return this.AddWhereField(internalName, valueString, dataType, operatorTag, out flag);
            }

            if (fieldNode.FirstChild.NextSibling != null)
            {
                DateTime time;
                XmlAttribute attribute2 = (XmlAttribute) fieldNode.FirstChild.NextSibling.Attributes.GetNamedItem("Type");
                if ((attribute2 != null) && (dataType.ToString() != attribute2.Value))
                {
                    attribute2.Value = dataType.ToString();
                }
                if ((operatorTag == CamlOperatorEnum.IsNull) || (operatorTag == CamlOperatorEnum.IsNotNull))
                {
                    fieldNode.RemoveChild(fieldNode.FirstChild.NextSibling);
                }
                XmlNode node = fieldNode.SelectSingleNode("Value");
                if (((dataType == DataTypeEnum.DateTime) && (valueString.Substring(0, 1) != "[")) && DateTime.TryParse(valueString, out time))
                {
                    valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(time);
                }
                if ((node != null) && (node.InnerText != valueString))
                {
                    node.InnerText = valueString;
                }
                return fieldNode;
            }
            if ((operatorTag != CamlOperatorEnum.IsNull) && (operatorTag != CamlOperatorEnum.IsNotNull))
            {
                DateTime time2;
                XmlNode newChild = this.camlDocument.CreateElement("Value");
                newChild.InnerText = valueString;
                XmlAttribute attribute3 = this.camlDocument.CreateAttribute("Type");
                attribute3.Value = dataType.ToString();
                if (((dataType == DataTypeEnum.DateTime) && (valueString.Substring(0, 1) != "[")) && DateTime.TryParse(valueString, out time2))
                {
                    valueString = CamlHelper.CreateISO8601DateTimeFromSystemDateTime(time2);
                }
                newChild.Attributes.Append(attribute3);
                newChild.InnerText = valueString;
                fieldNode.AppendChild(newChild);
            }
            return fieldNode;
        }

        public XmlNode BatchNode
        {
            get
            {
                if ((this.batchNode == null) && (this.camlDocument != null))
                {
                    this.batchNode = this.camlDocument.CreateElement(Batch.Tag);
                    this.UpdateBatchNode(Batch.PreCalc, "TRUE");
                    this.rootNode.AppendChild(this.batchNode);
                }
                return this.batchNode;
            }
        }

        public XmlDocument CamlDocument
        {
            get
            {
                return this.camlDocument;
            }
        }

        public CamlTypeEnum CamlType
        {
            get
            {
                return this.camlType;
            }
            set
            {
                this.camlType = value;
            }
        }

        public XmlNode ContainsNode
        {
            get
            {
                if (this.containsNode == null)
                {
                    this.containsNode = this.camlDocument.CreateElement(Contains.Tag);
                    this.RootNode.AppendChild(this.containsNode);
                }
                return this.containsNode;
            }
        }

        public bool IsQueryByFieldName
        {
            get
            {
                return this.isFieldRefName;
            }
            set
            {
                this.isFieldRefName = value;
                this.CheckFieldRefs();
            }
        }

        public XmlNode OrderByNode
        {
            get
            {
                if ((this.orderByNode == null) && (this.camlDocument != null))
                {
                    this.orderByNode = this.camlDocument.CreateElement(Query.OrderBy.Tag);
                    this.QueryNode.AppendChild(this.orderByNode);
                }
                return this.orderByNode;
            }
        }

        public XmlNode QueryNode
        {
            get
            {
                if ((this.queryNode == null) && (this.camlDocument != null))
                {
                    this.queryNode = this.camlDocument.CreateElement(Query.Tag);
                    switch (this.camlType)
                    {
                        case CamlTypeEnum.Query:
                            this.camlDocument.AppendChild(this.queryNode);
                            break;

                        case CamlTypeEnum.GetListItems:
                        case CamlTypeEnum.GetListItemChangesSinceToken:
                        case CamlTypeEnum.UpdateListItems:
                            this.RootNode.AppendChild(this.queryNode);
                            break;
                    }
                }
                return this.queryNode;
            }
        }

        public XmlNode QueryOptionsNode
        {
            get
            {
                if (this.queryOptionsNode == null)
                {
                    this.queryOptionsNode = this.camlDocument.CreateElement(QueryOptions.Tag);
                    this.RootNode.AppendChild(this.queryOptionsNode);
                }
                return this.queryOptionsNode;
            }
        }

        public XmlNode RootNode
        {
            get
            {
                if ((this.rootNode == null) && (this.camlDocument != null))
                {
                    this.rootNode = this.camlDocument.CreateElement(this.camlType.ToString());
                    this.camlDocument.AppendChild(this.rootNode);
                }
                return this.rootNode;
            }
        }

        public XmlNode ViewFieldsNode
        {
            get
            {
                if (this.viewFieldsNode == null)
                {
                    this.viewFieldsNode = this.camlDocument.CreateElement(ViewFields.Tag);
                    this.RootNode.AppendChild(this.viewFieldsNode);
                }
                return this.viewFieldsNode;
            }
        }

        public XmlNode WhereNode
        {
            get
            {
                if ((this.whereNode == null) && (this.camlDocument != null))
                {
                    this.whereNode = this.camlDocument.CreateElement(Query.Where.Tag);
                    this.QueryNode.AppendChild(this.whereNode);
                }
                return this.whereNode;
            }
        }
    }
}

